package com.loooooo.pm2024.web;

import com.fasterxml.jackson.databind.JsonNode;
import com.loooooo.pm2024.data.Result;
import com.loooooo.pm2024.modules.secu.LoginedUser;
import com.loooooo.pm2024.modules.secu.LoginedUserHolder;
import com.loooooo.pm2024.modules.secu.SessionCache;
import com.loooooo.pm2024.utils.JsonUtils;
import com.loooooo.pm2024.utils.JwtUtils;
import com.loooooo.pm2024.web.session.SessionUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;

@Component
public class MyFilter implements HandlerInterceptor {

    static PathMatcher pathMatcher = new AntPathMatcher();
    static long allowedClockSkewSeconds = 3600L * 24 * 365 * 1000;

    @Value("#{'${security.gateway.pass:/login,/logout,/**/download,/static/**,/buyer/**,/sys/user/login,/product/price/calculate}'.split(',')}")
    List<String> routePass;

    @Value("#{'${security.gateway.whiteIP:127.0.0.1}'.split(',')}")
    List<String> whiteIps;

//    @Autowired
//    HttpSession session;

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        LoginedUser loginedUser = LoginedUserHolder.get();


        String token = request.getHeader("Authorization");
        if (token == null) {
            token = request.getHeader("PM_ACCESS_TOKEN");
            if (token == null) {
                token = request.getHeader("access_token");
                if (token == null) {
                    token = request.getParameter("access_token");
                }
            }
        }
        //System.out.println(String.format("webfilteraccesstoken = '%s'", token));
        if (token != null && token.length() > 2) {

            String decodedToken = JwtUtils.parseToken(token);
            JsonNode node = JsonUtils.deserializeFromString(decodedToken, JsonNode.class);
            LoginedUser user = new LoginedUser();// = JsonUtils.deserializeFromString(decodedToken, LoginedUser.class);

            user.setUserId(node.get("userid").asLong());
            user.setUsername(node.get("username").asText());
            LoginedUserHolder.put(user);
            return true;

        }

        HttpSession session = SessionUtils.getSession(false);// request.getSession(false);
        if (session != null && null != session.getAttribute("username")) {
            if (loginedUser == null) {
                loginedUser = new LoginedUser();
                loginedUser.setUsername(session.getAttribute("username").toString());

                if (session.getAttribute("userid") != null)
                    loginedUser.setUserId(Long.parseLong(session.getAttribute("userid").toString()));
                if (session.getAttribute("type") != null)
                    loginedUser.setLoginType(session.getAttribute("type").toString());
                LoginedUserHolder.put(loginedUser);
            }
            return true;
        }
        HttpSession casSession = SessionUtils.getCASSession();// request.getSession(false);
        if (casSession != null && null != casSession.getAttribute("userid")) {
            if (loginedUser == null) {
                loginedUser = new LoginedUser();
                //loginedUser.setUsername(session.getAttribute("username").toString());

                if (casSession.getAttribute("userid") != null)
                    loginedUser.setUserId(Long.parseLong(casSession.getAttribute("userid").toString()));
//                loginedUser.setLoginType(Login.TYPE_CAS);
                LoginedUserHolder.put(loginedUser);
            }
            return true;
        }
        //来自CAS的session


        if (loginedUser != null) return true;
//        String jhtoken = request.getHeader("token");
//        if (jhtoken != null) {
//            Claims claims =  JwtUtils.parseToken(token, Settings.getTokenKey());
//        }

        for (String route : routePass) {
            if (pathMatcher.match(route, request.getRequestURI())) {
                //System.out.println(String.format("request %s match %s", request.getRequestURI(), route));
                return true;
            }
        }
        //地址白名单
        String requestIp = getRemoteIP(request);
        String[] ips = requestIp.split(",");
        for (String ip : ips) {
            if (whiteIps.contains(ip) || whiteIps.contains("*")) {
                //System.out.println(String.format("past remoteAddr %s", ip));
                return true;

            }
        }
        if (isAjax(request)) {
            response.setHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE);
            try {
                response.getOutputStream().write(JsonUtils.serializeToString(Result.error(401, "认证令牌无效或已失效，请重新登录。", null)).getBytes(StandardCharsets.UTF_8));
            } catch (IOException e) {
                e.printStackTrace();
            }
            return false;
        }
        String referer = request.getHeader("Referer");
        if (referer != null && !referer.contains("onlineedit") && session == null) {
            session = SessionUtils.getSession(true);
        }
        if (session != null && session.getAttribute("redirectUrl") == null) {
            String redirectUrl = request.getRequestURI();
            if (request.getQueryString() != null) redirectUrl += "?" + request.getQueryString();
            session.setAttribute("redirectUrl", redirectUrl);
        }
        response.sendRedirect("/login");
        //response.sendRedirect("/wechat/qrcode");
        return false;
    }

    public String getRemoteIP(HttpServletRequest request) {
        if (request.getHeader("x-forwarded-for") == null) {
            return request.getRemoteAddr();
        }
        return request.getHeader("x-forwarded-for");
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        SessionCache.remove();
    }

    private String getHost(HttpServletRequest request) {
        StringBuffer url = request.getRequestURL();
        return url.delete(url.length() - request.getRequestURI().length(), url.length()).toString();
    }


    static boolean isAjax(HttpServletRequest httpRequest) {
        return (httpRequest.getHeader("Accept") != null && httpRequest.getHeader("Accept").contains(MediaType.APPLICATION_JSON_VALUE))
                || (httpRequest.getHeader("X-Requested-With") != null
                && "XMLHttpRequest"
                .equals(httpRequest.getHeader("X-Requested-With").toString()));
    }

}
